;definir si (i j), puede ser comida por (x y)
(defun comible (i j x y)
  (or (= i x)
      (= j y)
      (= (- i j) (- x y))
      (= (+ i j) (+ x y))
  )
)



;Verificar si la posicion esta libre de ser comida 
(defun PosEsComible (i j tablero)
  (cond  ((endp tablero) nil)
         ;;Verifica si es comible por la primer posicion del tablero devuelve true
         ((comible i j (first (first tablero)) (second (first tablero))) t)
	 ;;Si no, vuelve a verificar con el resto del tablero:	
         (t (PosEsComible i j (rest tablero)))
  )
)


;;;Solucion:

(defun Reinas (N &optional (tablero nil) (i 0) (j 0))
  (unless (= j N)
    ;;Verifica si la nueva posicion esta libre de ser comida o no:
    (if (not (PosEsComible i j tablero))
      (if (= (+ 1 i) N)
        ;;Si ya coloque las N reinas, mostrar solucion:
        (print-tablero (reverse (cons (list i j) tablero)))
        ;;Sino, seguir probando posiciones, moviendo un lugar la fila:
        (Reinas N (cons (list i j) tablero) (+ 1 i) 0)
       )   
    )
    ;;Seguir con proxima columna:
    (Reinas N tablero i (+ 1 j))
    
  )
)


;;----------------------------------------------------------------------------------
;;Imprimir tablero

(defun print-tablero2 (tablero)
  (print tablero)
)

(defun print-tablero (tablero)
;  (sort tablero #'<= :key #'car)
  (format t "~%*")
  (print-horizontal-border tablero)
  (format t "*")
  (dotimes (row (length tablero))
    (format t "~%|")
    (dotimes (column (length tablero))
      (if (= column (second (assoc row tablero)))
          
        (format t " Q")
        (format t " .")))
    (format t " |"))
  (format t "~%*")
  (print-horizontal-border tablero)
  (format t "*"))


(defun print-horizontal-border (tablero)
  (dotimes (n (+ 1 (* 2 (length tablero))))
    (format t "-")))
